package com.sc.nft.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.sc.nft.dao.ActivityBasicsDao;
import com.sc.nft.dao.PrizeDrawActivitySettleRecordsDao;
import com.sc.nft.dao.UserPrizeDrawRecordsDao;
import com.sc.nft.entity.ActivityBasics;
import com.sc.nft.entity.UserInfo;
import com.sc.nft.entity.UserPrizeDrawRecords;
import com.sc.nft.entity.dto.BettingDTO;
import com.sc.nft.entity.dto.MyGuessDTO;
import com.sc.nft.entity.dto.NumberQueryListDTO;
import com.sc.nft.entity.dto.UserBettingDTO;
import com.sc.nft.entity.vo.*;
import com.sc.nft.enums.EquityPropsTypeEnum;
import com.sc.nft.enums.PrizeDrawActivityRewardsEnum;
import com.sc.nft.exception.GlobalRunTimeException;
import com.sc.nft.service.UserEquityPropsService;
import com.sc.nft.service.UserPrizeDrawRecordsService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 用户抽奖号码表服务接口实现
 *
 * @author Sun
 * @since 2023-09-14 11:33:11
 * @description 由 Mybatisplus Code Generator 创建
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class UserPrizeDrawRecordsServiceImpl implements UserPrizeDrawRecordsService {

    private final UserPrizeDrawRecordsDao userPrizeDrawRecordsDao;

    private final UserEquityPropsService userEquityPropsService;

    private final ActivityBasicsDao activityBasicsDao;
    private final PrizeDrawActivitySettleRecordsDao prizeDrawActivitySettleRecordsDao;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void userBetting(UserBettingDTO userBettingDTO, UserInfo userInfo) {
        if (!userInfo.getIsSm()) {
            throw new GlobalRunTimeException("未实名用户无法参与竞猜");
        }
        // 获取活动的基础数据
        ActivityBasics activityBasics = activityBasicsDao.getById(userBettingDTO.getId());
        if (BeanUtil.isEmpty(activityBasics)) {
            throw new GlobalRunTimeException("当前活动不存在");
        }
        if (activityBasics.getStatus().equals(0)) {
            throw new GlobalRunTimeException("当前活动不存在");
        }
        if (activityBasics.getStartTime().after(new Date())) {
            throw new GlobalRunTimeException("活动未开始");
        }
        if (activityBasics.getEndTime().before(new Date())) {
            throw new GlobalRunTimeException("活动已结束");
        }
        if (activityBasics.getLotteryStatus().equals(1)) {
            throw new GlobalRunTimeException("已开奖活动无法继续竞猜");
        }

        // 根据活动所需的道具,获取用户对应的道具
        Long propId = activityBasics.getPropId();
        Integer havingCountByUserId = userEquityPropsService.getHavingCountByUserId(propId, userInfo.getId());

        // 下注条件,用户需要多少个奖券
        int bettingCondition = userBettingDTO.getBetting().size();
        // 验证用户奖券,是否满足下注所需.
        if (havingCountByUserId<bettingCondition) {
            throw new GlobalRunTimeException(StrUtil.format("{}数量不足",activityBasics.getPropName()));
        }
        // 这个是把用户的号码组装成一个号码进行保存
        for (BettingDTO bettingDTO : userBettingDTO.getBetting()) {
            bettingDTO.combination();
        }
        // 入库,把用户的抽奖券消耗掉,这里需要知道用户的每个号码消耗了哪个奖券,所以循环操作
        for (int i = 0; i < bettingCondition; i++) {
            Long userPropId = userEquityPropsService.subVoucherIndependent(activityBasics.getPropId(), EquityPropsTypeEnum.RAFFLE_TICKET, userInfo.getId(), "竞猜抽奖券消耗", activityBasics.getId());
            BettingDTO bettingDTO = userBettingDTO.getBetting().get(i);
            UserPrizeDrawRecords userPrizeDrawRecords = BeanUtil.copyProperties(bettingDTO, UserPrizeDrawRecords.class);
            userPrizeDrawRecords.setUserId(userInfo.getId());
            userPrizeDrawRecords.setUserEquityPropsId(userPropId);
            userPrizeDrawRecords.setActivityId(activityBasics.getId());
            userPrizeDrawRecords.setActivityType(userBettingDTO.getActivityType());
            userPrizeDrawRecordsDao.save(userPrizeDrawRecords);
        }
    }

    @Override
    public List<String> creationVerify(UserBettingDTO userBettingDTO, UserInfo userInfo) {
        // 满足奖券,帮用户下单,在这个之前.验证用户是否有重复的单.
        // 重复的单需要给前端一个通知.在前端点击确定以后,重新唤醒一个新的接口进行下单.
        for (BettingDTO bettingDTO : userBettingDTO.getBetting()) {
            bettingDTO.combination();
        }
        List<String> collect = userBettingDTO.getBetting().stream().map(BettingDTO::getLotteryDrawResult).collect(Collectors.toList());
        List<UserPrizeDrawRecords> userPrizeDrawRecords = userPrizeDrawRecordsDao.withActivityIdVerifyUsersSerialNumber(userBettingDTO.getId(), userInfo.getId(), collect);
        return userPrizeDrawRecords.stream().map(UserPrizeDrawRecords::getLotteryDrawResult).collect(Collectors.toList());
    }
    @Override
    public Page<UserPrizeDrawRecords> myGuess(MyGuessDTO myGuessDTO, UserInfo user) {
        ActivityBasics activityBasics = activityBasicsDao.getById(myGuessDTO.getActivityId());
        return userPrizeDrawRecordsDao.myGuess(myGuessDTO,user,activityBasics);
    }
    @Override
    public List<WinnersListVO> listWinners(Long id) {
        return userPrizeDrawRecordsDao.listWinners(id);
    }
    @Override
    public List<NumberQueryListVO> numberQueryList(NumberQueryListDTO numberQueryListDTO) {
        return userPrizeDrawRecordsDao.numberQueryList(numberQueryListDTO);

    }

    @Override
    public List<MyListWinnersVO> myListWinners(Long activityId,UserInfo user) {
        return prizeDrawActivitySettleRecordsDao.myListWinners(activityId,user.getId());
    }

    @Override
    public List<ListOfWinnersVO> listOfWinners(Long activityId) {
        return prizeDrawActivitySettleRecordsDao.listOfWinners(activityId);
    }

    @Override
    public List<UserPrizeDrawRecords> getUserLotteryListByActivityIdAndTypeAndNumber(Long activityId, PrizeDrawActivityRewardsEnum rewardsType, Integer v1, Integer v2, Integer v3, Integer v4, Integer v5,ArrayList<Long> notInIds) {
        switch (rewardsType) {
            case SPECIAL_PRIZE:
                return  userPrizeDrawRecordsDao.getWinningNumberByActivityIdAndNumber(activityId,v1,v2,v3,v4,v5,notInIds);
            case  FIRST_PRIZE:
                return userPrizeDrawRecordsDao.getWinningNumberByActivityIdAndNumber(activityId,null,v2,v3,v4,v5,notInIds);
            case  SECOND_PRIZE:
                return  userPrizeDrawRecordsDao.getWinningNumberByActivityIdAndNumber(activityId,null,null,v3,v4,v5,notInIds);
            case  THIRD_PRIZE:
                return userPrizeDrawRecordsDao.getWinningNumberByActivityIdAndNumber(activityId,null,null,null,v4,v5,notInIds);
            case  FOURTH_PRIZE:
                return  userPrizeDrawRecordsDao.getWinningNumberByActivityIdAndNumber(activityId,null,null,null,null,v5,notInIds);
        }
        return Lists.newArrayList();
    }

    @Override
    public Boolean updateWinPrizeLotteryAndTypeNameByIds(Long activityId,ArrayList<Long> ids, PrizeDrawActivityRewardsEnum type, String name) {
        return userPrizeDrawRecordsDao.updateWinPrizeLotteryAndTypeNameByIds(activityId,ids,type,name);
    }

    @Override
    public Boolean updateLosingLotteryAndTypeNameByIds(Long activityId, ArrayList<Long> notInIds) {
        return userPrizeDrawRecordsDao.updateLosingLotteryAndTypeNameByIds(activityId,notInIds);
    }

    @Override
    public MyNumberVO myNumber(Long id) {
        return activityBasicsDao.myNumber(id);
    }
}